package fons.model.query.fun;

import java.util.List;

import com.google.common.collect.Lists;

public class ZipFun implements Function {
	private final List<ListFun> lists;
	private final Function zipper;
	private final int max;
	
	public ZipFun() {
		this(new ListFun());
	}
	
	public ZipFun(Function zipper) {
		this.zipper = zipper;
		this.lists = Lists.newArrayList();
		this.max = 0;
	}
	
	public ZipFun(Function zipper, List<ListFun> lists, int max) {
		this.zipper = zipper;
		this.lists = Lists.newArrayList(lists);
		this.max = max;
	}
	
	public ZipFun(Function zipper, List<ListFun> lists, ListFun other, int max) {
		this.zipper = zipper;
		this.lists = Lists.newArrayList(lists);
		this.lists.add(other);
		
		if (other.get().size() > max) {
			this.max = other.get().size();
		} else {
			this.max = max;
		}
	}
	
	@Override
	public Function apply(Function other) {
		Function fun = other.apply();		
		if (fun instanceof ListFun) return new ZipFun(zipper, lists, (ListFun) fun, max);
		else return new ZipFun(other, lists, max);
	}

	@Override
	public Function apply() {
		Function result = new ListFun();
		
		for (int i = 0; i < max; ++i) {
			Function zipper = this.zipper;
			for (ListFun list: lists) {
				if (i < list.get().size()) {
					zipper = zipper.apply(list.get().get(i));
				}
			}
			result = result.apply(zipper.apply());
		}
		
		return result.apply();
	}
}
